package main

import (
	"context"
	"fmt"
	"github.com/coreos/etcd/clientv3"
	"time"
)

func main() {

	var (
		config clientv3.Config
		client *clientv3.Client
		err    error
		//用于读写etcd的键值对
		kv clientv3.KV

		getResp *clientv3.GetResponse
	)

	config = clientv3.Config{
		Endpoints: []string{"10.70.30.73:2379"},
		//AutoSyncInterval:     0,
		DialTimeout: 3 * time.Second,
		//DialKeepAliveTime:    0,
		//DialKeepAliveTimeout: 0,
		//MaxCallSendMsgSize:   0,
		//MaxCallRecvMsgSize:   0,
		//TLS:                  nil,
		//Username:             "",
		//Password:             "",
		//RejectOldCluster:     false,
		//DialOptions:          nil,
		//LogConfig:            nil,
		//Context:              nil,
		//PermitWithoutStream:  false,
	}

	if client, err = clientv3.New(config); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("hello,etcd  ")

	//统一用kv对象操作
	kv = clientv3.NewKV(client)

	//context是golang中常用的，put是个网络操作，如果中间出现超时，可以用context将它关闭，context.TODO为项目开发初期，代表不取消context,相当于一个占位符，默认值而已
	if putResp, err := kv.Put(context.TODO(), "/cron/jobs/job1", "hello,job1"); err != nil {
		fmt.Println(err)
	} else {
		// clusterId ：集群id
		//memberid ：返回给客户端请求数据的id
		// revision indicates 代表 着一个处理结果，成功后肯定会大于之前的revision
		//raft_term 当前第几任任期
		fmt.Println("revision:", putResp.Header.Revision)
		fmt.Println("clusterId:", putResp.Header.ClusterId)
		fmt.Println("raft term:", putResp.Header.RaftTerm)
		fmt.Println("memberId", putResp.Header.MemberId)
	}

	//覆盖key，得到前一个值，用PrevKv, 需要显示的设置第三个值，具体可以看一下put操作的op结构体，里面包括range，txn等。返回的是字节数组，可以用With查看所有相关命令
	putRespCover, err := kv.Put(context.TODO(), "/cron/jobs/job1", "new job1 value", clientv3.WithPrevKV())

	fmt.Println("putRespCover", string(putRespCover.PrevKv.Value))

	//如果覆盖的值不存在，prevKV将返回nil
	putRespNew, err := kv.Put(context.TODO(), "newKey", " value0", clientv3.WithPrevKV())

	fmt.Println("putRespNew:", putRespNew.PrevKv)
	fmt.Printf("putRespNew.mod_revision:%d", putRespNew.PrevKv.ModRevision)

	//get方法,这里可以清楚看到create_revision，mod_revision，version（代表操作次数）

	//第一次创建一个新key如下
	//[key:"newKeyGet" create_revision:61 mod_revision:61 version:1 value:" newKeyGetValue" ]
	//重复执行上面的操作，如下，自从这个key相关的version代表操作这个key的数量，而create_和mod代表所有key的一个revision的递增值
	//key:"newKeyGet" create_revision:61 mod_revision:65 version:2 value:" newKeyGetValue" ]

	kv.Put(context.TODO(), "newKeyGet", " newKeyGetValue", clientv3.WithPrevKV())
	fmt.Println("=========get============")
	getResp, err = kv.Get(context.TODO(), "newKeyGet" /*clientv3.WithCountOnly()*/)
	if err != nil {
		fmt.Printf(err.Error())
	} else {
		fmt.Println("get new key value is ：", getResp.Kvs)
	}
	// 命令行操作，注意需要V3参数
	//root@udev:/home/tb/soure_install/etcd-v3.3.2-linux-amd64# ETCDCTL_API=3 ./etcdctl  get "/cron/jobs/job1"
	///cron/jobs/job1
	//hello,job1

}
